home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Misc / GetDXVer / getdxver.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  24.1 KB  |  560 lines

  1. //-----------------------------------------------------------------------------
  2. // File: GetDXVer.cpp
  3. //
  4. // Desc: Demonstrates how applications can detect what version of DirectX
  5. //       is installed.
  6. //
  7. // (C) Copyright Microsoft Corp.  All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define INITGUID
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <tchar.h>
  13. #include <dxdiag.h>
  14.  
  15.  
  16. HRESULT GetDirectXVersionViaDxDiag( DWORD* pdwDirectXVersionMajor, DWORD* pdwDirectXVersionMinor, TCHAR* pcDirectXVersionLetter );
  17. HRESULT GetDirectXVerionViaFileVersions( DWORD* pdwDirectXVersionMajor, DWORD* pdwDirectXVersionMinor, TCHAR* pcDirectXVersionLetter );
  18. HRESULT GetFileVersion( TCHAR* szPath, ULARGE_INTEGER* pllFileVersion );
  19. ULARGE_INTEGER MakeInt64( WORD a, WORD b, WORD c, WORD d );
  20. int CompareLargeInts( ULARGE_INTEGER ullParam1, ULARGE_INTEGER ullParam2 );
  21.  
  22.  
  23.  
  24.  
  25. //-----------------------------------------------------------------------------
  26. // Name: GetDXVersion()
  27. // Desc: This function returns the DirectX version.
  28. // Arguments: 
  29. //      pdwDirectXVersion - This can be NULL.  If non-NULL, the return value is:
  30. //              0x00000000 = No DirectX installed
  31. //              0x00010000 = DirectX 1.0 installed
  32. //              0x00020000 = DirectX 2.0 installed
  33. //              0x00030000 = DirectX 3.0 installed
  34. //              0x00030001 = DirectX 3.0a installed
  35. //              0x00050000 = DirectX 5.0 installed
  36. //              0x00060000 = DirectX 6.0 installed
  37. //              0x00060100 = DirectX 6.1 installed
  38. //              0x00060101 = DirectX 6.1a installed
  39. //              0x00070000 = DirectX 7.0 installed
  40. //              0x00070001 = DirectX 7.0a installed
  41. //              0x00080000 = DirectX 8.0 installed
  42. //              0x00080100 = DirectX 8.1 installed
  43. //              0x00080101 = DirectX 8.1a installed
  44. //              0x00080102 = DirectX 8.1b installed
  45. //              0x00080200 = DirectX 8.2 installed
  46. //              0x00090000 = DirectX 9.0 installed
  47. //      strDirectXVersion - Destination string to receive a string name of the DirectX Version.  Can be NULL.
  48. //      cchDirectXVersion - Size of destination buffer in characters.  Length should be at least 10 chars.
  49. // Returns: S_OK if the function succeeds.  
  50. //          E_FAIL if the DirectX version info couldn't be determined.
  51. //
  52. // Please note that this code is intended as a general guideline. Your
  53. // app will probably be able to simply query for functionality (via
  54. // QueryInterface) for one or two components.
  55. //
  56. // Also please ensure your app will run on future releases of DirectX.
  57. // For example:
  58. //     "if( dwDirectXVersion != 0x00080100 ) return false;" is VERY BAD. 
  59. //     "if( dwDirectXVersion < 0x00080100 ) return false;" is MUCH BETTER.
  60. //-----------------------------------------------------------------------------
  61. HRESULT GetDXVersion( DWORD* pdwDirectXVersion, TCHAR* strDirectXVersion, int cchDirectXVersion )
  62. {
  63.     bool bGotDirectXVersion = false;  
  64.  
  65.     // Init values to unknown
  66.     if( pdwDirectXVersion )
  67.         *pdwDirectXVersion = 0;
  68.     if( strDirectXVersion && cchDirectXVersion > 0 )
  69.         strDirectXVersion[0] = 0;
  70.  
  71.     DWORD dwDirectXVersionMajor = 0;
  72.     DWORD dwDirectXVersionMinor = 0;
  73.     TCHAR cDirectXVersionLetter = ' ';
  74.  
  75.     // First, try to use dxdiag's COM interface to get the DirectX version.  
  76.     // The only downside is this will only work on DX9 or later.
  77.     if( SUCCEEDED( GetDirectXVersionViaDxDiag( &dwDirectXVersionMajor, &dwDirectXVersionMinor, &cDirectXVersionLetter ) ) )
  78.         bGotDirectXVersion = true;
  79.   
  80.     if( !bGotDirectXVersion )
  81.     {
  82.         // Getting the DirectX version info from DxDiag failed, 
  83.         // so most likely we are on DX8.x or earlier
  84.         if( SUCCEEDED( GetDirectXVerionViaFileVersions( &dwDirectXVersionMajor, &dwDirectXVersionMinor, &cDirectXVersionLetter ) ) )
  85.             bGotDirectXVersion = true;
  86.     }
  87.  
  88.     // If both techniques failed, then return E_FAIL
  89.     if( !bGotDirectXVersion )
  90.         return E_FAIL;
  91.         
  92.     // Set the output values to what we got and return       
  93.     cDirectXVersionLetter = (char)tolower(cDirectXVersionLetter);
  94.     
  95.     if( pdwDirectXVersion )
  96.     {
  97.         // If pdwDirectXVersion is non-NULL, then set it to something 
  98.         // like 0x00080102 which would represent DX8.1b
  99.         DWORD dwDirectXVersion = dwDirectXVersionMajor;
  100.         dwDirectXVersion <<= 8;
  101.         dwDirectXVersion += dwDirectXVersionMinor;
  102.         dwDirectXVersion <<= 8;
  103.         if( cDirectXVersionLetter >= 'a' && cDirectXVersionLetter <= 'z' )
  104.             dwDirectXVersion += (cDirectXVersionLetter - 'a') + 1;
  105.         
  106.         *pdwDirectXVersion = dwDirectXVersion;
  107.     }
  108.     
  109.     if( strDirectXVersion && cchDirectXVersion > 0 )
  110.     {
  111.         // If strDirectXVersion is non-NULL, then set it to something 
  112.         // like "8.1b" which would represent DX8.1b
  113.         if( cDirectXVersionLetter == ' ' )
  114.             _sntprintf( strDirectXVersion, cchDirectXVersion, TEXT("%d.%d"), dwDirectXVersionMajor, dwDirectXVersionMinor );
  115.         else
  116.             _sntprintf( strDirectXVersion, cchDirectXVersion, TEXT("%d.%d%c"), dwDirectXVersionMajor, dwDirectXVersionMinor, cDirectXVersionLetter );
  117.         strDirectXVersion[cchDirectXVersion-1] = 0;
  118.     }
  119.     
  120.    return S_OK;
  121. }
  122.  
  123.  
  124.  
  125.  
  126. //-----------------------------------------------------------------------------
  127. // Name: GetDirectXVersionViaDxDiag()
  128. // Desc: Tries to get the DirectX version from DxDiag's COM interface
  129. //-----------------------------------------------------------------------------
  130. HRESULT GetDirectXVersionViaDxDiag( DWORD* pdwDirectXVersionMajor, 
  131.                                     DWORD* pdwDirectXVersionMinor, 
  132.                                     TCHAR* pcDirectXVersionLetter )
  133. {
  134.     HRESULT hr;
  135.     bool bCleanupCOM = false;
  136.  
  137.     bool bSuccessGettingMajor = false;
  138.     bool bSuccessGettingMinor = false;
  139.     bool bSuccessGettingLetter = false;
  140.     
  141.     // Init COM.  COM may fail if its already been inited with a different 
  142.     // concurrency model.  And if it fails you shouldn't release it.
  143.     hr = CoInitialize(NULL);
  144.     bCleanupCOM = SUCCEEDED(hr);
  145.  
  146.     // Get an IDxDiagProvider
  147.     bool bGotDirectXVersion = false;
  148.     IDxDiagProvider* pDxDiagProvider = NULL;
  149.     hr = CoCreateInstance( CLSID_DxDiagProvider,
  150.                            NULL,
  151.                            CLSCTX_INPROC_SERVER,
  152.                            IID_IDxDiagProvider,
  153.                            (LPVOID*) &pDxDiagProvider );
  154.     if( SUCCEEDED(hr) )
  155.     {
  156.         // Fill out a DXDIAG_INIT_PARAMS struct
  157.         DXDIAG_INIT_PARAMS dxDiagInitParam;
  158.         ZeroMemory( &dxDiagInitParam, sizeof(DXDIAG_INIT_PARAMS) );
  159.         dxDiagInitParam.dwSize                  = sizeof(DXDIAG_INIT_PARAMS);
  160.         dxDiagInitParam.dwDxDiagHeaderVersion   = DXDIAG_DX9_SDK_VERSION;
  161.         dxDiagInitParam.bAllowWHQLChecks        = false;
  162.         dxDiagInitParam.pReserved               = NULL;
  163.  
  164.         // Init the m_pDxDiagProvider
  165.         hr = pDxDiagProvider->Initialize( &dxDiagInitParam ); 
  166.         if( SUCCEEDED(hr) )
  167.         {
  168.             IDxDiagContainer* pDxDiagRoot = NULL;
  169.             IDxDiagContainer* pDxDiagSystemInfo = NULL;
  170.  
  171.             // Get the DxDiag root container
  172.             hr = pDxDiagProvider->GetRootContainer( &pDxDiagRoot );
  173.             if( SUCCEEDED(hr) ) 
  174.             {
  175.                 // Get the object called DxDiag_SystemInfo
  176.                 hr = pDxDiagRoot->GetChildContainer( L"DxDiag_SystemInfo", &pDxDiagSystemInfo );
  177.                 if( SUCCEEDED(hr) )
  178.                 {
  179.                     VARIANT var;
  180.                     VariantInit( &var );
  181.  
  182.                     // Get the "dwDirectXVersionMajor" property
  183.                     hr = pDxDiagSystemInfo->GetProp( L"dwDirectXVersionMajor", &var );
  184.                     if( SUCCEEDED(hr) && var.vt == VT_UI4 )
  185.                     {
  186.                         if( pdwDirectXVersionMajor )
  187.                             *pdwDirectXVersionMajor = var.ulVal; 
  188.                         bSuccessGettingMajor = true;
  189.                     }
  190.                     VariantClear( &var );
  191.  
  192.                     // Get the "dwDirectXVersionMinor" property
  193.                     hr = pDxDiagSystemInfo->GetProp( L"dwDirectXVersionMinor", &var );
  194.                     if( SUCCEEDED(hr) && var.vt == VT_UI4 )
  195.                     {
  196.                         if( pdwDirectXVersionMinor )
  197.                             *pdwDirectXVersionMinor = var.ulVal; 
  198.                         bSuccessGettingMinor = true;
  199.                     }
  200.                     VariantClear( &var );
  201.  
  202.                     // Get the "szDirectXVersionLetter" property
  203.                     hr = pDxDiagSystemInfo->GetProp( L"szDirectXVersionLetter", &var );
  204.                     if( SUCCEEDED(hr) && var.vt == VT_BSTR && SysStringLen( var.bstrVal ) != 0 )
  205.                     {
  206. #ifdef UNICODE
  207.                         *pcDirectXVersionLetter = var.bstrVal[0]; 
  208. #else
  209.                         char strDestination[10];
  210.                         WideCharToMultiByte( CP_ACP, 0, var.bstrVal, -1, strDestination, 10*sizeof(CHAR), NULL, NULL );
  211.                         if( pcDirectXVersionLetter )
  212.                             *pcDirectXVersionLetter = strDestination[0]; 
  213. #endif
  214.                         bSuccessGettingLetter = true;
  215.                     }
  216.                     VariantClear( &var );
  217.  
  218.                     // If it all worked right, then mark it down
  219.                     if( bSuccessGettingMajor && bSuccessGettingMinor && bSuccessGettingLetter )
  220.                         bGotDirectXVersion = true;
  221.  
  222.                     pDxDiagSystemInfo->Release();
  223.                 }
  224.  
  225.                 pDxDiagRoot->Release();
  226.             }
  227.         }
  228.  
  229.         pDxDiagProvider->Release();
  230.     }
  231.  
  232.     if( bCleanupCOM )
  233.         CoUninitialize();
  234.         
  235.     if( bGotDirectXVersion )
  236.         return S_OK;
  237.     else
  238.         return E_FAIL;
  239. }
  240.  
  241.  
  242.  
  243.  
  244. //-----------------------------------------------------------------------------
  245. // Name: GetDirectXVerionViaFileVersions()
  246. // Desc: Tries to get the DirectX version by looking at DirectX file versions
  247. //-----------------------------------------------------------------------------
  248. HRESULT GetDirectXVerionViaFileVersions( DWORD* pdwDirectXVersionMajor, 
  249.                                          DWORD* pdwDirectXVersionMinor, 
  250.                                          TCHAR* pcDirectXVersionLetter )
  251. {       
  252.     ULARGE_INTEGER llFileVersion;  
  253.     TCHAR szPath[512];
  254.     TCHAR szFile[512];
  255.     BOOL bFound = false;
  256.  
  257.     if( GetSystemDirectory( szPath, MAX_PATH ) != 0 )
  258.     {
  259.         szPath[MAX_PATH-1]=0;
  260.             
  261.         // Switch off the ddraw version
  262.         _tcscpy( szFile, szPath );
  263.         _tcscat( szFile, TEXT("\\ddraw.dll") );
  264.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  265.         {
  266.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 2, 0, 95 ) ) >= 0 ) // Win9x version
  267.             {                    
  268.                 // flle is >= DX1.0 version, so we must be at least DX1.0
  269.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 1;
  270.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  271.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  272.                 bFound = true;
  273.             }
  274.  
  275.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 3, 0, 1096 ) ) >= 0 ) // Win9x version
  276.             {                    
  277.                 // flle is is >= DX2.0 version, so we must DX2.0 or DX2.0a (no redist change)
  278.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 2;
  279.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  280.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  281.                 bFound = true;
  282.             }
  283.  
  284.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 4, 0, 68 ) ) >= 0 ) // Win9x version
  285.             {                    
  286.                 // flle is is >= DX3.0 version, so we must be at least DX3.0
  287.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 3;
  288.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  289.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  290.                 bFound = true;
  291.             }
  292.         }
  293.         
  294.         // Switch off the d3drg8x.dll version
  295.         _tcscpy( szFile, szPath );
  296.         _tcscat( szFile, TEXT("\\d3drg8x.dll") );
  297.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  298.         {
  299.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 4, 0, 70 ) ) >= 0 ) // Win9x version
  300.             {                    
  301.                 // d3drg8x.dll is the DX3.0a version, so we must be DX3.0a or DX3.0b  (no redist change)
  302.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 3;
  303.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  304.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT('a');
  305.                 bFound = true;
  306.             }
  307.         }       
  308.  
  309.         // Switch off the ddraw version
  310.         _tcscpy( szFile, szPath );
  311.         _tcscat( szFile, TEXT("\\ddraw.dll") );
  312.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  313.         {
  314.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 5, 0, 155 ) ) >= 0 ) // Win9x version
  315.             {                    
  316.                 // ddraw.dll is the DX5.0 version, so we must be DX5.0 or DX5.2 (no redist change)
  317.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 5;
  318.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  319.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  320.                 bFound = true;
  321.             }
  322.  
  323.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 6, 0, 318 ) ) >= 0 ) // Win9x version
  324.             {                    
  325.                 // ddraw.dll is the DX6.0 version, so we must be at least DX6.0
  326.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 6;
  327.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  328.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  329.                 bFound = true;
  330.             }
  331.  
  332.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 6, 0, 436 ) ) >= 0 ) // Win9x version
  333.             {                    
  334.                 // ddraw.dll is the DX6.1 version, so we must be at least DX6.1
  335.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 6;
  336.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 1;
  337.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  338.                 bFound = true;
  339.             }
  340.         }
  341.  
  342.         // Switch off the dplayx.dll version
  343.         _tcscpy( szFile, szPath );
  344.         _tcscat( szFile, TEXT("\\dplayx.dll") );
  345.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  346.         {
  347.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 6, 3, 518 ) ) >= 0 ) // Win9x version
  348.             {                    
  349.                 // ddraw.dll is the DX6.1 version, so we must be at least DX6.1a
  350.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 6;
  351.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 1;
  352.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT('a');
  353.                 bFound = true;
  354.             }
  355.         }
  356.  
  357.         // Switch off the ddraw version
  358.         _tcscpy( szFile, szPath );
  359.         _tcscat( szFile, TEXT("\\ddraw.dll") );
  360.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  361.         {
  362.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 7, 0, 700 ) ) >= 0 ) // Win9x version
  363.             {                    
  364.                 // TODO: find win2k version
  365.                 
  366.                 // ddraw.dll is the DX7.0 version, so we must be at least DX7.0
  367.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 7;
  368.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  369.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  370.                 bFound = true;
  371.             }
  372.         }
  373.  
  374.         // Switch off the dinput version
  375.         _tcscpy( szFile, szPath );
  376.         _tcscat( szFile, TEXT("\\dinput.dll") );
  377.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  378.         {
  379.             if( CompareLargeInts( llFileVersion, MakeInt64( 4, 7, 0, 716 ) ) >= 0 ) // Win9x version
  380.             {                    
  381.                 // ddraw.dll is the DX7.0 version, so we must be at least DX7.0a
  382.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 7;
  383.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  384.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT('a');
  385.                 bFound = true;
  386.             }
  387.         }
  388.  
  389.         // Switch off the ddraw version
  390.         _tcscpy( szFile, szPath );
  391.         _tcscat( szFile, TEXT("\\ddraw.dll") );
  392.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  393.         {
  394.             if( (HIWORD(llFileVersion.HighPart) == 4 && CompareLargeInts( llFileVersion, MakeInt64( 4, 8, 0, 400 ) ) >= 0) || // Win9x version
  395.                 (HIWORD(llFileVersion.HighPart) == 5 && CompareLargeInts( llFileVersion, MakeInt64( 5, 1, 2258, 400 ) ) >= 0) ) // Win2k/WinXP version
  396.             {                    
  397.                 // ddraw.dll is the DX8.0 version, so we must be at least DX8.0 or DX8.0a (no redist change)
  398.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 8;
  399.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  400.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  401.                 bFound = true;
  402.             }
  403.         }
  404.  
  405.         _tcscpy( szFile, szPath );
  406.         _tcscat( szFile, TEXT("\\d3d8.dll"));
  407.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  408.         {
  409.             if( (HIWORD(llFileVersion.HighPart) == 4 && CompareLargeInts( llFileVersion, MakeInt64( 4, 8, 1, 881 ) ) >= 0) || // Win9x version
  410.                 (HIWORD(llFileVersion.HighPart) == 5 && CompareLargeInts( llFileVersion, MakeInt64( 5, 1, 2600, 881 ) ) >= 0) ) // Win2k/WinXP version
  411.             {                    
  412.                 // d3d8.dll is the DX8.1 version, so we must be at least DX8.1
  413.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 8;
  414.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 1;
  415.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  416.                 bFound = true;
  417.             }
  418.  
  419.             if( (HIWORD(llFileVersion.HighPart) == 4 && CompareLargeInts( llFileVersion, MakeInt64( 4, 8, 1, 901 ) ) >= 0) || // Win9x version
  420.                 (HIWORD(llFileVersion.HighPart) == 5 && CompareLargeInts( llFileVersion, MakeInt64( 5, 1, 2600, 901 ) ) >= 0) ) // Win2k/WinXP version
  421.             {                    
  422.                 // d3d8.dll is the DX8.1a version, so we must be at least DX8.1a
  423.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 8;
  424.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 1;
  425.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT('a');
  426.                 bFound = true;
  427.             }
  428.         }
  429.  
  430.         _tcscpy( szFile, szPath );
  431.         _tcscat( szFile, TEXT("\\mpg2splt.ax"));
  432.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  433.         {
  434.             if( CompareLargeInts( llFileVersion, MakeInt64( 6, 3, 1, 885 ) ) >= 0 ) // Win9x/Win2k/WinXP version
  435.             {                    
  436.                 // quartz.dll is the DX8.1b version, so we must be at least DX8.1b
  437.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 8;
  438.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 1;
  439.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT('b');
  440.                 bFound = true;
  441.             }
  442.         }
  443.  
  444.         _tcscpy( szFile, szPath );
  445.         _tcscat( szFile, TEXT("\\dpnet.dll"));
  446.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  447.         {
  448.             if( (HIWORD(llFileVersion.HighPart) == 4 && CompareLargeInts( llFileVersion, MakeInt64( 4, 9, 0, 134 ) ) >= 0) || // Win9x version
  449.                 (HIWORD(llFileVersion.HighPart) == 5 && CompareLargeInts( llFileVersion, MakeInt64( 5, 2, 3677, 134 ) ) >= 0) ) // Win2k/WinXP version
  450.             {                    
  451.                 // dpnet.dll is the DX8.2 version, so we must be at least DX8.2
  452.                 if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 8;
  453.                 if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 2;
  454.                 if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  455.                 bFound = true;
  456.             }
  457.         }
  458.  
  459.         _tcscpy( szFile, szPath );
  460.         _tcscat( szFile, TEXT("\\d3d9.dll"));
  461.         if( SUCCEEDED( GetFileVersion( szFile, &llFileVersion ) ) )
  462.         {
  463.             // File exists, but be at least DX9
  464.             if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 9;
  465.             if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  466.             if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  467.             bFound = true;
  468.         }
  469.     }
  470.  
  471.     if( !bFound )
  472.     {
  473.         // No DirectX installed
  474.         if( pdwDirectXVersionMajor ) *pdwDirectXVersionMajor = 0;
  475.         if( pdwDirectXVersionMinor ) *pdwDirectXVersionMinor = 0;
  476.         if( pcDirectXVersionLetter ) *pcDirectXVersionLetter = TEXT(' ');
  477.     }
  478.  
  479.     return S_OK;
  480. }
  481.  
  482.  
  483.  
  484.  
  485. //-----------------------------------------------------------------------------
  486. // Name: GetFileVersion()
  487. // Desc: Returns ULARGE_INTEGER with a file version of a file, or a failure code.
  488. //-----------------------------------------------------------------------------
  489. HRESULT GetFileVersion( TCHAR* szPath, ULARGE_INTEGER* pllFileVersion )
  490. {   
  491.     if( szPath == NULL || pllFileVersion == NULL )
  492.         return E_INVALIDARG;
  493.  
  494.     DWORD dwHandle;
  495.     UINT  cb;
  496.     cb = GetFileVersionInfoSize( szPath, &dwHandle );
  497.     if (cb > 0)
  498.     {
  499.         BYTE* pFileVersionBuffer = new BYTE[cb];
  500.         if( pFileVersionBuffer == NULL )
  501.             return E_OUTOFMEMORY;
  502.  
  503.         if (GetFileVersionInfo( szPath, 0, cb, pFileVersionBuffer))
  504.         {
  505.             VS_FIXEDFILEINFO* pVersion = NULL;
  506.             if (VerQueryValue(pFileVersionBuffer, TEXT("\\"), (VOID**)&pVersion, &cb) && 
  507.                 pVersion != NULL) 
  508.             {
  509.                 pllFileVersion->HighPart = pVersion->dwFileVersionMS;
  510.                 pllFileVersion->LowPart  = pVersion->dwFileVersionLS;
  511.                 delete[] pFileVersionBuffer;
  512.                 return S_OK;
  513.             }
  514.         }
  515.  
  516.         delete[] pFileVersionBuffer;
  517.     }
  518.  
  519.     return E_FAIL;
  520. }
  521.  
  522.  
  523.  
  524.  
  525. //-----------------------------------------------------------------------------
  526. // Name: MakeInt64()
  527. // Desc: Returns a ULARGE_INTEGER where a<<48|b<<32|c<<16|d<<0
  528. //-----------------------------------------------------------------------------
  529. ULARGE_INTEGER MakeInt64( WORD a, WORD b, WORD c, WORD d )
  530. {
  531.     ULARGE_INTEGER ull;
  532.     ull.HighPart = MAKELONG(b,a);
  533.     ull.LowPart = MAKELONG(d,c);
  534.     return ull;
  535. }
  536.  
  537.  
  538.  
  539.  
  540. //-----------------------------------------------------------------------------
  541. // Name: CompareLargeInts()
  542. // Desc: Returns 1 if ullParam1 > ullParam2
  543. //       Returns 0 if ullParam1 = ullParam2
  544. //       Returns -1 if ullParam1 < ullParam2
  545. //-----------------------------------------------------------------------------
  546. int CompareLargeInts( ULARGE_INTEGER ullParam1, ULARGE_INTEGER ullParam2 )
  547. {
  548.     if( ullParam1.HighPart > ullParam2.HighPart )
  549.         return 1;
  550.     if( ullParam1.HighPart < ullParam2.HighPart )
  551.         return -1;
  552.  
  553.     if( ullParam1.LowPart > ullParam2.LowPart )
  554.         return 1;
  555.     if( ullParam1.LowPart < ullParam2.LowPart )
  556.         return -1;
  557.  
  558.     return 0;
  559. }
  560.